---
import type { Framework } from '@ag-grid-types';
import Note from '@ag-website-shared/components/alert/Note';
import Warning from '@ag-website-shared/components/alert/Warning';
import { DocsNav } from '@ag-website-shared/components/docs-navigation/DocsNav';
import styles from '@ag-website-shared/components/page-styles/docs.module.scss';
import { DOCS_TAB_ITEM_ID_PREFIX } from '@ag-website-shared/constants';
import { Header } from '@components/docs/components/Header';
import { SideNavigation } from '@components/pages-navigation/components/SideNavigation';
import { FRAMEWORK_REDIRECT_PATH, FRAMEWORKS, PRODUCTION_GRID_SITE_URL } from '@constants';
import Layout from '@layouts/Layout.astro';
import { getIsArchive } from '@utils/env';
import { getFrameworkDisplayText } from '@utils/framework';
import { getErrorText } from '@utils/getErrorText';
import { getHeadings, getTopHeading } from '@utils/markdoc/getHeadings';
import { pathJoin } from '@utils/pathJoin';
import { urlWithPrefix } from '@utils/urlWithPrefix';
import { getCollection, getEntry, render, type CollectionEntry } from 'astro:content';
import {
    AG_GRID_ERRORS,
    type ErrorId,
} from '../../../../../../packages/ag-grid-community/src/validation/errorMessages/errorText';

interface Params {
    framework: Framework;
    code: string;
}
interface Props {
    errorPage?: CollectionEntry<'errors'>;
}

export async function getStaticPaths() {
    const errors = await getCollection('errors');
    return FRAMEWORKS.flatMap((framework: Framework) => {
        return Object.keys(AG_GRID_ERRORS).map((codeNum) => {
            const code = codeNum.toString();
            const errorPage = errors.find(({ id }) => id === code);
            return {
                params: {
                    framework,
                    code,
                },
                props: {
                    errorPage,
                },
            };
        });
    });
}

const { framework, code } = Astro.params as Params;
const { errorPage } = Astro.props as Props;
const errorCode = parseInt(code, 10) as ErrorId;
const frameworkDisplayText = framework === 'javascript' ? '' : getFrameworkDisplayText(framework);
const title = `AG Grid ${frameworkDisplayText} Error #${code}`;
const description = errorPage?.data.description ? errorPage?.data.description : '';

const { Content } = errorPage ? await render(errorPage) : { Content: undefined };
const { data: docsNavData } = (await getEntry('docsNav', 'nav')) as CollectionEntry<'docsNav'>;
const { data: allErrorLinks } = (await getEntry('errorLinks', 'links')) as CollectionEntry<'errorLinks'>;

const errorLinks = allErrorLinks.filter((e) => e.errorIds.includes(errorCode)) ?? [];
const path = Astro.url.pathname;
const pageName = `errors/${code}`;
const defaultErrorText = getErrorText({ errorCode });

const getTabItemSlug = (id: string) => `${DOCS_TAB_ITEM_ID_PREFIX}${id}`;
const topHeading = getTopHeading(title);
const fullErrorTextHeading = { slug: getTabItemSlug('full-error-text'), depth: 2, text: 'Full Error Text' };
const relatedDocPages = { slug: getTabItemSlug('related-doc-pages'), depth: 2, text: 'Related Doc Pages' };
let headings = errorPage
    ? await getHeadings({
          title,
          pageName,
          markdocContent: errorPage.body,
          framework,
          getTabItemSlug,
      })
    : [topHeading, fullErrorTextHeading];

if (errorPage) {
    // insert FullErrorTextHandling in second position as the errorPage brings its own top heading
    headings = [headings[0], fullErrorTextHeading, ...headings.slice(1)];
}

if (errorLinks.length > 0) {
    headings.push(relatedDocPages);
}

const isArchive = getIsArchive();
const migrationUrl = pathJoin(PRODUCTION_GRID_SITE_URL, FRAMEWORK_REDIRECT_PATH, 'migration');
---

<Layout
    title={title}
    description={description}
    showSearchBar={true}
    showDocsNav={true}
    hidePageFromSearchEngines={true}
>
    <div class:list={[styles.contentViewport, 'layout-grid']}>
        <DocsNav client:load menuData={docsNavData} framework={framework} pageName={pageName} />

        <div id="doc-content" class:list={[styles.docPage, styles.errorPage]}>
            <Header client:load title={title} framework={framework} path={path} menuItems={docsNavData.sections} />

            {
                isArchive && (
                    <Warning>
                        You are using an older version of AG Grid. To upgrade, please see our{' '}
                        <a href={migrationUrl}>migration guides</a>.
                    </Warning>
                )
            }

            <div class={styles.pageSections}>
                <h2 id={fullErrorTextHeading.slug}>{fullErrorTextHeading.text}</h2>
                <div class="missing-params-message">
                    <Warning>
                        Full error message cannot be shown because there are missing parameters in the URL. Please
                        follow the full link from the developer tool logs.
                    </Warning>
                </div>
                <div class="full-error-message">
                    <pre id="errorCodeText">{defaultErrorText}</pre>
                    <Note>To show this error text in the dev console, import the <code>ValidationModule</code>.</Note>
                </div>

                {
                    errorLinks.length > 0 ? (
                        <>
                            <h2 id={relatedDocPages.slug}>{relatedDocPages.text}</h2>
                            <p>
                                The following documentation pages should provide additional context / guidance on how to
                                resolve this error.
                            </p>
                            <ul>
                                {errorLinks.map((e) => (
                                    <li>
                                        <a href={urlWithPrefix({ framework, url: e.url })}>{e.text}</a>
                                        {e.description ? <span> - {e.description}</span> : undefined}
                                    </li>
                                ))}
                            </ul>
                        </>
                    ) : undefined
                }

                {Content ? <Content framework={framework} /> : undefined}
            </div>
        </div>

        <SideNavigation client:load headings={headings} />
    </div>
</Layout>

<script>
    import { getErrorText } from '@utils/getErrorText';
    import type { ErrorId } from '../../../../../../packages/ag-grid-community/src/validation/errorMessages/errorText';
    import { VERSION } from '../../../../../../packages/ag-grid-community/src/version';
    import { getErrorRedirectBaseUrl } from '@utils/getErrorRedirectBaseUrl';
    import { pathJoin } from '@utils/pathJoin';

    const MISSING_PARAMS_MESSAGE_SELECTOR = '.missing-params-message';
    const FULL_ERROR_MESSAGE_SELECTOR = '.full-error-message';
    const ERROR_CODE_TEXT_ID = 'errorCodeText';

    // Get errorCode from url, so it doesn't need to be passed
    // in from Astro and we can import in this script
    const errorCode = parseInt(window.location.pathname.split('/').filter(Boolean).slice(-1)[0], 10) as ErrorId;
    const searchParams = new URLSearchParams(window.location.search);
    const { _version_, ...params } = Object.fromEntries(searchParams.entries());

    if (!_version_) {
        // Missing version number, show a warning message
        const missingParamsMessage = (document.querySelector(MISSING_PARAMS_MESSAGE_SELECTOR) as HTMLElement)!;
        const fullErrorMessage = (document.querySelector(FULL_ERROR_MESSAGE_SELECTOR) as HTMLElement)!;

        missingParamsMessage.style.display = 'block';
        fullErrorMessage.style.display = 'none';
    } else {
        const errorText = getErrorText({ errorCode, params });
        const errorRedirectBaseUrl = getErrorRedirectBaseUrl({ errorVersion: _version_, pageVersion: VERSION });

        if (errorRedirectBaseUrl) {
            const redirectUrl = pathJoin(errorRedirectBaseUrl, window.location.pathname, window.location.search);
            window.location.replace(redirectUrl);
        }

        const errorCodeTextEl = document.getElementById(ERROR_CODE_TEXT_ID);
        if (errorCodeTextEl) {
            errorCodeTextEl.textContent = errorText;
        }
    }
</script>
